package com.softwareengineering.trafficapplicationv2;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup.LayoutParams;
import android.widget.RelativeLayout;
import android.widget.TextView;

/**
 * This file is part of the Traffic Simulation Application.
 * The Traffic Simulation Application is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * The Traffic Simulation Application is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with the Traffic Simulation Application.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * @file SimCanvas.java
 * @author (c) Martin Treiber, http://traffic-simulation.de/
 * @alterations David Black, Chris Nelson, and Garrett Stibbs, (c) December 03, 2012
 * @description SimCanvas extends the SurfaceView and is the View responsible for game
 * 				presentation. It owns its own SimThread that handles drawing and
 * 				physics updates for the traffic simulation.
 * 
 */

class SimCanvas extends SurfaceView implements SurfaceHolder.Callback {

	// handle to the TextView responsible for displaying score
	private TextView mScoreText;

	// handle to the SimThread responsible for drawing and physics updates and traffic operations
	private SimThread thread;

	//	###################
	//		Constructor
	//	###################
	
	public SimCanvas(Context context, RelativeLayout contentView, int choice_Szen, double density, double qIn, double perTr,
			double p_factor, double deltaB,
			double p_factorRamp, double deltaBRamp,
			int tsleep_ms) {
		super(context);	// call super

		setKeepScreenOn(true);	// keep screen on as long as SimCanvas is visible (so screen doesn't shut off during gameplay)
		setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));	// stretch SimCanvas to fill screen
		SurfaceHolder holder = getHolder();	// get handle to SurfaceHolder
		holder.addCallback(this);	// set SurfaceHolder callback

		// handler to allow interaction between SimThread and GUI TextView displaying score
		Handler handler = new Handler() {
			@Override
			public void handleMessage(Message m) {
				mScoreText.setText("Score: " + m.getData().getInt("score"));	// set text to "Score: X" where X=score
			}
		};
		
		// initialize SimThread with all desired attributes
		thread = new SimThread(
				holder,	// pass handle to SurfaceHolder
				handler,	// pass handle to Handler
				choice_Szen,	// pass level code
				density,	//	pass traffic density
				qIn,	// pass main inflow
				perTr,	// pass percentage trucks
				p_factor,	// pass politeness factor
				deltaB,	// pass changing lane threshold
				p_factorRamp,	// pass politeness factor ramp
				deltaBRamp,	// pass changing lane threshold ramp
				tsleep_ms);	// pass sleep time in milliseconds

		contentView.addView(this, 0); // add SimCanvas to parent at bottom index (under all other elements, i.e. controls)
	}

	//	###############
	//		Getters
	//	###############
	
	// returns handle to SimThread associated with SimCanvas
	public SimThread getThread() {
		return thread; // return handle to SimThread
	}

	//	###############
	//		Setters
	//	###############
	
	// sets handle to TextView used for displaying score
	public void setTextView(TextView textView) {
		mScoreText = textView;	// set TextView for displaying score
	}
	
	//	#################
	//		Callbacks
	//	#################

	// callback invoked when the surface dimensions change
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		thread.setSurfaceSize(width, height);	// notify SimThread of size change
	}

	// callback invoked when the surface has been created
	public void surfaceCreated(SurfaceHolder holder) {
		if (thread.getState() == Thread.State.TERMINATED)	// if terminated thread (i.e. recreating from activity stopped)
			thread = new SimThread();	// create new SimThread
		
		thread.setRunning(true);	// set thread to running
		thread.start();	// start thread
	}

	// callback invoked when the surface has been destroyed
	public void surfaceDestroyed(SurfaceHolder holder) {
		boolean retry = true;	// allows us to loop until success
		thread.setRunning(false);	// stop thread
		
		while (retry) {	// loop until successful
			try {
				thread.join();	// attempt to join thread
				retry = false;	// do not retry if successful
			} catch (InterruptedException e) {}
		}
	}
}